package socket1;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 服务端
 */
public class Server {
    //1. 成员变量,创建serverSocket总机
    private ServerSocket serverSocket;
    //由于需要间服务器接收到的消息进行转发给所有人，因此需要定义一个全局的集合，用于存储所有客户端的输出流
    //private List<PrintWriter> allOut=new ArrayList<>();
    //实现私聊功能
    private Map<String,PrintWriter> allOut=new HashMap<>();
    //2. 构造方法
    public  Server(){
        //2.1 创建serverSocket对象 传入端口号,即在服务器端监听的端口号
        try {
            System.out.println("服务器启动>>");
            serverSocket=new ServerSocket(8088);
            System.out.println("服务器启动成功");
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
    //3. 启动服务
    public void start(){
        try {
            while (true){
                //3.1 监听客户端的连接
                System.out.println("等待客户端连接...");
                Socket socket=serverSocket.accept();
                System.out.println("客户端连接成功");
                //
                Runnable runnable=new ClientHandler(socket);
                Thread t1=new Thread(runnable);
                t1.start();

            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        Server server=new Server();
        server.start();
    }
    //多线程解决问题
    private class ClientHandler implements Runnable{
        private Socket socket;
        private String host;//记录客户端主机名
        private String nickName;
        public ClientHandler(Socket socket){
            this.socket=socket;
            this.host=socket.getInetAddress().getHostAddress();
        }
        @Override
        public void run(){
            //3.2 获取输入流,读取客户端发送过来的数据
            PrintWriter pw=null;
            try {
                InputStream is=socket.getInputStream();
                InputStreamReader isr=new InputStreamReader(is,StandardCharsets.UTF_8);
                BufferedReader br=new BufferedReader(isr);
                nickName=br.readLine();

                //3.3 获取输出流,向客户端发送数据
                OutputStream os= socket.getOutputStream();
                OutputStreamWriter osw=new OutputStreamWriter(os,StandardCharsets.UTF_8);
                BufferedWriter bw=new BufferedWriter(osw);
                pw=new PrintWriter(bw,true);

                //当获取到客户端的输入流时，进行保存到集合中
                synchronized (allOut) {
                    allOut.put(nickName,pw);
                }
                sendMessage(nickName+host+"上线了，当前在线人数:"+allOut.size());



                String Message=null;
                while ((Message=br.readLine())!=null){

                    //System.out.println(host+"客户端说:"+Message);
                    //pw.println(host+"转发客户端说"+Message);//转发客户的消息
                    //将消息进行广播，对该方法进行抽离复用
                    if (Message.startsWith("@")){
                        //调用私聊方法
                        sendMessageTosomeone(Message);
                    }else {
                        sendMessage(nickName + host + "转发客户端说" + Message);
                    }
                }
            } catch (IOException e) {
                //客户端异常断开，不是错误，不做处理
            } finally {
                //当线程断开时，流段，(Message=br.readLine())!=null)为假，循环结束
                //线程断开，代码执行到该处，可以进行对集合中输出流的移除操作
                synchronized (allOut) {
                    allOut.remove(nickName);
                }
                sendMessage(nickName+host+"下线了，当前在线人数:"+allOut.size());
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        public void sendMessage(String message){
            System.out.println(message);
            synchronized (allOut) {
                for (PrintWriter o : allOut.values()) {
                    o.println(message);
                }
            }
        }
        //定义私聊方法
        public void sendMessageTosomeone(String message){
            if (message.matches("@.+:.+")) {
                String toNickName = message.substring(1, message.indexOf(":"));
                if (allOut.containsKey(toNickName)) {


                    PrintWriter pw = allOut.get(toNickName);

                    String toMessage = message.substring(message.indexOf(":") + 1);

                    pw.println(nickName + "悄悄对你说" + toMessage);
                } else {
                    //给该用户提示
                    PrintWriter pw = allOut.get(nickName);
                    pw.println("该用户不存在");
                }
            }else {
                PrintWriter pw = allOut.get(nickName);
                pw.println("私聊格式不正确，格式应当为 @对方昵称:私聊消息");
            }
        }



    }



}
